/************************************************************************/
/* Game                                                                 */
/************************************************************************/
#include "Game/Managers/InputManager.h"

namespace TD_Game {

	interaction_t InputManager::processKeyboard(SDL_Event * pEvent) {
		
		interaction_t interaction;
		interaction.type = noInteraction;

		if(m_pMenuPanel->isVisible()) {
			interaction_t tempInteraction = m_pMenuPanel->processEvent(*pEvent);
			if(tempInteraction.type != noInteraction) {
				return tempInteraction;
			}
		}
		
		//If a key was pressed 
		if( pEvent->type == SDL_KEYDOWN ) { 
			//Set the proper message surface
			switch( pEvent->key.keysym.sym ) {
				case SDLK_ESCAPE:
					if(m_isTowerSelected)
						m_isTowerSelected = false;
					
					interaction.type = towerHideInserting;
					SDLCursor::hideCursor(false);

					/*interaction.type = gameExit;*/
				break;

				case SDLK_RCTRL:
				case SDLK_LCTRL:
					m_controlKeyDown = true;
				break;
			} 
		} else if( pEvent->type == SDL_KEYUP) {
			switch( pEvent->key.keysym.sym ) {
				case SDLK_RCTRL:
				case SDLK_LCTRL:
					m_controlKeyDown = false;
				break;
			}
		}

		return(interaction);
	}

	interaction_t InputManager::processMouseOnSubElements(SDL_Event *event) {
		Coord2D mousePos;
		interaction_t interaction;
		interaction.type = noInteraction;

		if(event->type == SDL_MOUSEMOTION) { 
			mousePos.x = event->motion.x;
			mousePos.y = event->motion.y;
		} else if (event->type == SDL_MOUSEBUTTONDOWN) {
			mousePos.x = event->button.x;
			mousePos.y = event->button.y;
		} else { //No interaction to treat
			return interaction;
		}

		

		if(m_pTowerInfo->collisionCheck(mousePos) && m_pTowerInfo->isVisible()) {
			interaction_t tempInteraction = m_pTowerInfo->processEvent(*event);
			if(tempInteraction.type != noInteraction) {
				return tempInteraction;
			}
		}

		if(m_pTowerMenu->collisionCheck(mousePos) && m_pTowerMenu->isVisible()) {
			interaction_t tempInteraction = m_pTowerMenu->processEvent(*event);
			
			if(tempInteraction.type != noInteraction) {
				if(tempInteraction.type == towerHideInserting)
					m_isTowerSelected = false;
				return tempInteraction;
			}
		}

		

		return (interaction);
	}

	interaction_t  InputManager::processMouse(SDL_Event *event) {
		interaction_t tempInteraction = processMouseOnSubElements(event);
		
		switch(tempInteraction.type) {
			case towerSelected:
				m_isTowerSelected = true;
				m_selectedTowerType = tempInteraction.towerType;
			break;
			
			case noInteraction:
				Coord2D eventPosition;
				if(event->type == SDL_MOUSEMOTION) {
					eventPosition.x = event->motion.x - m_pScreen->getCanvasPosition().x;
					eventPosition.y = event->motion.y - m_pScreen->getCanvasPosition().y;

				} else if (event->type == SDL_MOUSEBUTTONDOWN) {
					eventPosition.x = event->button.x - m_pScreen->getCanvasPosition().x;
					eventPosition.y = event->button.y - m_pScreen->getCanvasPosition().y;
				} else {
					return(tempInteraction); //Avoid invalid processing
				}

				if(m_isTowerSelected) {
					if(event->type == SDL_MOUSEMOTION) {
						if(isInsideCanvas(eventPosition)) {
							SDLCursor::hideCursor(true);
							int towerIndex_x = eventPosition.x/(m_terrainTilesize.x/2);
							int towerIndex_y = eventPosition.y/(m_terrainTilesize.y/2);

							int index_i = eventPosition.y/m_terrainTilesize.y;
							int index_j = eventPosition.x/m_terrainTilesize.x;
							bool specialPos = towerIndex_x == 13 && (towerIndex_y == 6 || towerIndex_y == 7);
							if((*m_pTerrain->getPathMatrix())(index_i, index_j) == 1 || specialPos) {
								tempInteraction.type = towerInsertingInvalid;
							} else {
								tempInteraction.type = towerInserting;
							}

							tempInteraction.towerType = m_selectedTowerType;
							tempInteraction.value = TowerFactory::getBaseTowerReference(m_selectedTowerType)->getPrice();
							if(towerIndex_x <= 1) {
								tempInteraction.position.x = towerIndex_x * (m_terrainTilesize.x/2) +
									m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4) + 15;
							} else if(towerIndex_x > 10) {
								tempInteraction.position.x = towerIndex_x * (m_terrainTilesize.x/2) +
									m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4) + 15;
							} else {
								tempInteraction.position.x = towerIndex_x * (m_terrainTilesize.x/2) +
									m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4) + 25;
							}

							tempInteraction.position.y = towerIndex_y * (m_terrainTilesize.x/2) +
								m_pScreen->getCanvasPosition().y + (m_terrainTilesize.x/4);


						} 
					} else if(event->type == SDL_MOUSEBUTTONDOWN) {
						if( event->button.button == SDL_BUTTON_LEFT ) { 
							if(isInsideCanvas(eventPosition)) {
								SDLCursor::hideCursor(false);
								Coord2D towerPosition;
								int towerIndex_x = eventPosition.x/(m_terrainTilesize.x/2);
								int towerIndex_y = eventPosition.y/(m_terrainTilesize.y/2);

								towerPosition.x = towerIndex_x * (m_terrainTilesize.x/2) +
									m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4);

								towerPosition.y = towerIndex_y * (m_terrainTilesize.y/2) - 30 +
									m_pScreen->getCanvasPosition().y + (m_terrainTilesize.y/4);

								tempInteraction.type = towerInserted;

								tempInteraction.towerType = m_selectedTowerType;
								tempInteraction.position.x = towerIndex_x * (m_terrainTilesize.x/2) +
									m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4);

								tempInteraction.position.y = towerIndex_y * (m_terrainTilesize.x/2) +
									m_pScreen->getCanvasPosition().y + (m_terrainTilesize.x/4) - 25;
								tempInteraction.value = TowerFactory::getBaseTowerReference(m_selectedTowerType)->getPrice();

								if(towerIndex_x <= 1) {
									tempInteraction.position.x = towerIndex_x * (m_terrainTilesize.x/2) +
										m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4) + 15;
								} else if(towerIndex_x > 10) {
									tempInteraction.position.x = towerIndex_x * (m_terrainTilesize.x/2) +
										m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4) + 15;
								} else {
									tempInteraction.position.x = towerIndex_x * (m_terrainTilesize.x/2) +
										m_pScreen->getCanvasPosition().x + (m_terrainTilesize.x/4) + 25;
								}
								m_isTowerSelected = m_controlKeyDown;
							} 
						} else {
							tempInteraction.type = towerHideInserting;
							m_isTowerSelected = false;
						}
					} 
				} else { // If no tower is selected
					if(event->type == SDL_MOUSEBUTTONDOWN) {
						SDLCursor::hideCursor(false);

						eventPosition.x = event->button.x;
						eventPosition.y = event->button.y;

						if( event->button.button == SDL_BUTTON_LEFT ) {
							const map<unsigned int, BaseMario *> *m_pCreeps =  & MarioManager::getInstance()->getObjectMap();
							map<unsigned int, BaseMario *>::const_iterator iter = m_pCreeps->begin();


							if(m_pStartButton->collisionCheck(eventPosition)) {
								SDLCursor::setCursor(handCursor);
								tempInteraction.type = startNextWave;
								return(tempInteraction);
							}

							if(m_pMenuButton->collisionCheck(eventPosition)) {
								SDLCursor::setCursor(handCursor);
								tempInteraction.type = showMenu;
								return(tempInteraction);
							}

							while(iter != m_pCreeps->end()) {
								if(iter->second->collisionCheck(eventPosition)) {
									m_pSelectedCreep = iter->second;
									m_selectedCreepID = iter->first;
									tempInteraction.type = creepShowInfo;
									
									return(tempInteraction); //To avoid invalid processing 
								}
								iter++;
							}

							const map<unsigned int, BaseTower*> *m_pTowers = & TowerManager::getInstance()->getObjectMap();
							map<unsigned int, BaseTower *>::const_iterator towerIter = m_pTowers->begin();
							while(towerIter != m_pTowers->end()) {
								if(towerIter->second->collisionCheck(eventPosition)) {
									m_pSelectedTower = towerIter->second;
									tempInteraction.type = towerShowInfo;
									return(tempInteraction); //To avoid invalid processing 
								}
								towerIter++;
							}
							tempInteraction.type = towerHideInfo;
							return(tempInteraction);

						}
					} else if(event->type == SDL_MOUSEMOTION) {
						SDLCursor::hideCursor(false);
						eventPosition.x = event->motion.x;
						eventPosition.y = event->motion.y;
						
						if(m_pStartButton->collisionCheck(eventPosition)) {
							SDLCursor::setCursor(handCursor);
							tempInteraction.type = noInteraction;
							return(tempInteraction);
						}

						const map<unsigned int, BaseMario *> *m_pCreeps =  & MarioManager::getInstance()->getObjectMap();
						map<unsigned int, BaseMario *>::const_iterator iter = m_pCreeps->begin();
						while(iter != m_pCreeps->end()) {
							if(iter->second->collisionCheck(eventPosition)) {
								SDLCursor::setCursor(handCursor);
								tempInteraction.type = noInteraction;
								return(tempInteraction);
							}
							iter++;
						}

						const map<unsigned int, BaseTower*> *m_pTowers = & TowerManager::getInstance()->getObjectMap();
						map<unsigned int, BaseTower *>::const_iterator towerIter = m_pTowers->begin();
						while(towerIter != m_pTowers->end()) {
							if(towerIter->second->collisionCheck(eventPosition)) {
								SDLCursor::setCursor(handCursor);
								tempInteraction.type = noInteraction;
								return(tempInteraction);
							}
							towerIter++;
						}
						SDLCursor::hideCursor(false);
						//If no tower/creep selected or mouse over
						SDLCursor::setCursor(arrowCursor);
						if(m_isTowerSelected)
							m_isTowerSelected = false;

						tempInteraction.type = towerHideInserting;
					}
				}
			break;
		} // End of switch

		return(tempInteraction);
	}

	void InputManager::render(SDL_Surface *const g_destSurface, unsigned int deltaTime) {
		m_pStartButton->render(g_destSurface, deltaTime);
		m_pMenuButton->render(g_destSurface, deltaTime);
	}

	/************************************************************************/
	/* ctors and dtors                                                      */
	/************************************************************************/

	InputManager::InputManager() {

		m_pCreepInfo = NULL;
		m_pTowerInfo = NULL;
		m_pTowerMenu = NULL;
		m_controlKeyDown = false;
	}

	InputManager::InputManager(TerrainTilemap *g_pTerrain, TowerInfoPanel *g_pTowerInfo, 
							TowerMenuPanel *g_pTowerMenuPanel, TD_GUI::MarioInfoPanel *g_pMarioInfoPanel, 
							MenuPanel *g_pMenuPanel) {

		m_pTerrain = g_pTerrain;
		m_terrainTilesize = m_pTerrain->getTilesize() * 3;
		m_pTowerInfo = g_pTowerInfo;
		m_pTowerMenu = g_pTowerMenuPanel;
		m_pCreepInfo = g_pMarioInfoPanel;
		m_pMenuPanel = g_pMenuPanel;
		m_isTowerSelected = false;
		m_controlKeyDown = false;

		m_pStartButton = new BaseButton(Coord2D(0.83147*screenWidth, 0.85625*screenHeight), Coord2D(149, 72),
			TD_Resources::ResourceManager::loadImage("GUI/Buttons/startButton.png"));
		m_pMenuButton = new BaseButton(Coord2D(0.81147*screenWidth, 0.00375*screenHeight), Coord2D(165, 38), 
			TD_Resources::ResourceManager::loadImage("GUI/Buttons/menuButton.png"));

#ifdef _WII
		//Wii mote initilization
		WPAD_SetVRes(0, 640, 480);
		WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
#endif

		m_pCursorTile = new Tile(Coord2D(05, 45), Coord2D(24, 25), imgTile, NULL, TD_Resources::ResourceManager::loadImage("GUI/Icons/bowser icon.png", Color::PINK));

		
	}

	InputManager::~InputManager() {

		//The only object that is from input manager ownership
		Utils::safeDelete<Tile>(m_pCursorTile);
	}

	/************************************************************************/
	/* Functionalities                                                      */
	/************************************************************************/
	interaction_t InputManager::process(Screen *g_pRenderScreen , unsigned int deltaTime) {
		m_pScreen = g_pRenderScreen;
		interaction_t tempInteraction;
		tempInteraction.type = noInteraction;

#ifdef _WII
		WPAD_ScanPads();
		u32 pressed = WPAD_ButtonsDown(0);

		// IR Movement
		WPAD_IR(0, &m_wiiIr);

		if (pressed & WPAD_BUTTON_HOME) {
			exit(0);
		}
#endif
		/*Coord2D cursorPos(m_wiiIr.x, m_wiiIr.y);
		m_pCursorTile->setPosition(cursorPos);*/


		SDL_Event event;
		while(SDL_PollEvent( &event )) {
			tempInteraction = processKeyboard(&event);

			if(tempInteraction.type != noInteraction) {
				return tempInteraction;
			}

			tempInteraction = processMouse(&event);
			

			if(tempInteraction.type != noInteraction) {
				return tempInteraction;
			}
			if(event.type == SDL_QUIT) {
				tempInteraction.type = gameExit;
			}
		}

		render(m_pScreen->getRootScreen(), deltaTime);
		return(tempInteraction);
	}

}